package JET.graphics;

import JET.Animator;
import JET.geom.Rect2d;
import JET.geom.Vec2d;

import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import JET.physics.BodyFactory;
import JET.physics.Mass;
import JET.physics.Spring;
import JET.physics.bodies.SpringBody;
import JET.physics.Wall;
import JET.StaticActions;
import JET.Centers.ControlCenter;
import JET.Constants;
import JET.Frames.DataModels.DataModelsFactory;
import JET.MouseStuff.MouseHelper;
import JET.MouseStuff.MouseOTFMode;
import JET.MouseStuff.MouseOTFSubMode;
import JET.MouseStuff.MouseSubMode;
import JET.MouseStuff.Tasks.*;
import JET.SA.*;
import JET.Scene;
import JET.SceneHelper;
import JET.SceneItem;
import JET.editor.SelectionGroup;
import JET.physics.RSpring;
import JET.physics.bodies.Body;
import JET.physics.bodies.RigidBody;
import JET.physics.bodies.RigidBodyFactory;
import JET.physics.bodies.RigidBodyHelper;
import JET.physics.engine.JETContext;
import java.awt.Component;
import java.util.Collection;
import java.util.Collections;

/**
 *
 * @author 057Ry
 */
public class GraphicPanelMouseListener implements MouseListener, Constants
{
    static final ControlCenter CC = ControlCenter.getInstance();
    private Component owner;
    private GraphicPanel gp;
    private Scene scene;

    public GraphicPanelMouseListener(Component owner) {
        this.owner = owner;
        gp = (GraphicPanel) owner;
        this.scene = CC.getScene(((GraphicPanel)owner).getSceneName());
    }

    public void mouseClicked(MouseEvent evt) 
    {
        if ( evt.getButton() == MouseEvent.BUTTON1 )
            switch( CC.MC.getMouseMode() )
            {
                case SELECT_ALL_ITEMS : 
                case ROTATE :
                case SCALE:
                case COPY_SELECTED_ITEMS :
                    selectSpringBody(evt);
                    break;
                case MOVE_MASSES : findActualBody(evt); break;
            }
        else if ( evt.getButton() == MouseEvent.BUTTON2 )
        {
        }
        else if ( evt.getButton() == MouseEvent.BUTTON3 )
        {
            Rect2d rect2d = buildCatchArea();
            SpringBody sb = SceneHelper.getSpringBodyAt(scene, scene.EC.engCursor);

            if (!SceneHelper.isMouseOverAnything(scene, rect2d) && sb==null)
            {
                CC.GUIC.showPopupScene(evt);
            }
            else
            {
                if (sb!=null && SceneHelper.getItemsInRect(scene, buildCatchArea()).getMassList().isEmpty())
                {
                    SA_SpringBody.setCurrentSpringBody(sb, scene, true);
                    CC.GUIC.showPopupSpringBody(evt);
                    return;
                }
                else
                {
                    switch( CC.MC.getMouseMode() )
                    {
                        case ADD_SINGLE_WALL :
                        case ADD_SINGLE_SPRING :
                            CC.MC.setMouseSubMode(MouseSubMode.FIND_FIRST_OBJECT);
                            startAddSpring(evt);
                            owner.repaint();
                            break;
                        case ADD_SINGLE_RSPRING :
                            CC.MC.setMouseSubMode(MouseSubMode.FIND_FIRST_OBJECT);
                            startAddRSpring1(evt);
                            owner.repaint();
                            break;
                        case ROTATE : breakRotation(evt); break;
                    }
                }
            }
        }
    }

    public void mousePressed(MouseEvent evt)
    {
//        RigidBody rb = SceneHelper.getRigidBodyAt(CC.getCurrentScene(), CC.getCurrentScene().EC.engCursor);
//        if (rb!=null) {
//            System.out.println("scene: "+CC.getCurrentScene().EC.engCursor);
//            System.out.println("rb: "+rb.sceneToBase(CC.getCurrentScene().EC.engCursor));
//        }

        owner.requestFocus();
        int index = -1;
        if ( evt.getButton() == MouseEvent.BUTTON1 )
            if ( scene.GC.isDrawActionFrame() &&
                 (index=CC.getActionFrameSideBoxIndexAt(scene.EC.scrCursor, scene)) != -1 )
            {
                CC.MC.mouseLastCursor = owner.getCursor();
                
                if (index==1) {
                    CC.MC.setMouseOTFMode( MouseOTFMode.SCALE_ACTION_FRAME_NW );
                    scene.EC.setCursor( new Cursor(Cursor.NW_RESIZE_CURSOR) );
                }
                else if (index==2) {
                    CC.MC.setMouseOTFMode( MouseOTFMode.SCALE_ACTION_FRAME_N );
                    scene.EC.setCursor( new Cursor(Cursor.N_RESIZE_CURSOR) );
                }
                else if (index==3){
                    CC.MC.setMouseOTFMode( MouseOTFMode.SCALE_ACTION_FRAME_NE );
                    scene.EC.setCursor( new Cursor(Cursor.NE_RESIZE_CURSOR) );
                }
                else if (index==4){
                    CC.MC.setMouseOTFMode( MouseOTFMode.SCALE_ACTION_FRAME_E );
                    scene.EC.setCursor( new Cursor(Cursor.E_RESIZE_CURSOR) );
                }
                else if (index==5){
                    CC.MC.setMouseOTFMode( MouseOTFMode.SCALE_ACTION_FRAME_SE);
                    scene.EC.setCursor( new Cursor(Cursor.SE_RESIZE_CURSOR) );
                }
                else if (index==6){
                    CC.MC.setMouseOTFMode( MouseOTFMode.SCALE_ACTION_FRAME_S );
                    scene.EC.setCursor( new Cursor(Cursor.S_RESIZE_CURSOR) );
                }
                else if (index==7){
                    CC.MC.setMouseOTFMode( MouseOTFMode.SCALE_ACTION_FRAME_SW );
                    scene.EC.setCursor( new Cursor(Cursor.SW_RESIZE_CURSOR) );
                }
                else if (index==8){
                    CC.MC.setMouseOTFMode( MouseOTFMode.SCALE_ACTION_FRAME_W );
                    scene.EC.setCursor( new Cursor(Cursor.W_RESIZE_CURSOR) );
                }

                CC.MC.mouseVec = new Vec2d(scene.EC.currentBody.getBoundingArea().getMinX(),scene.EC.currentBody.getBoundingArea().getMinY());
                CC.MC.mouseVec2 = new Vec2d(scene.EC.currentBody.getBoundingArea().getMaxX() ,scene.EC.currentBody.getBoundingArea().getMaxY());

                CC.MC.setMouseOTFSubMode( MouseOTFSubMode.DO_NOTHING );
                scene.EC.transformSelectionGroup.clear();
                if (scene.EC.currentBody instanceof SpringBody) {
                    Collection<Mass> massCol = ((SpringBody)scene.EC.currentBody).getMassListSync();
                    synchronized(massCol) {
                        for(Mass mass : massCol)
                            scene.EC.transformSelectionGroup.addMass( new Mass(mass));
                    }
                } else if (scene.EC.currentBody instanceof RigidBody) {
                    // TODO: ...
                }
            }
            else
                switch( CC.MC.getMouseMode() )
                {
                    case ADD_MANY_MASS : startAddManyMass2d(evt); break;
                    case MOVE_MASSES : startMoveItems(evt); break;
                    case ADD_SINGLE_MASS : addMass2d(evt); break;
                    case ADD_SINGLE_WALL :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_FIRST_OBJECT : startAddWall2d(evt); break;
                            case FIND_SECOND_OBJECT : stopAddWall2d(evt); break;
                        }
                        break;
                    case ADD_SINGLE_SPRING :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_FIRST_OBJECT : startAddSpring(evt); break;
                            case FIND_SECOND_OBJECT : stopAddSpring(evt); break;
                        }
                        break;
                    case ADD_SINGLE_RSPRING :
                        switch(CC.MC.getMouseSubMode()) {
                            case FIND_FIRST_OBJECT : startAddRSpring1(evt); break;
                            case FIND_SECOND_OBJECT : startAddRSpring2(evt); break;
                            case FIND_THIRD_OBJECT : stopAddRSpring(evt); break;
                        }
                        break;
                    case SET_MOVEABLE : setMoveable(evt); break;
                    case CREATE_CIRCLE :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_FIRST_OBJECT : startCreateCircle(evt); break;
                        }
                        break;
                    case CREATE_SQUARENET :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_FIRST_OBJECT : startCreateSquareNet(evt); break;
                        }
                        break;
                    case SELECT_ALL_ITEMS :
                    case SELECT_MASSES :
                    case SELECT_SPRINGS :
                    case SELECT_RSPRINGS :
                    case SELECT_WALLS :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_FIRST_OBJECT : startSelection(evt); break;
                        }
                        break;
                    case SELECT_MASSES_IN_ORDER :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_FIRST_OBJECT : startSelectionInOrder(evt); break;
                        }
                        break;
                    case ROTATE :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_FIRST_OBJECT : startRotation(evt); break;
                        }
                        break;
                    case SCALE :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_FIRST_OBJECT : startScaling(evt); break;
                        }
                        break;
                    case COPY_SELECTED_ITEMS : copySelectedItems(evt); break;
                }
        else if ( evt.getButton() == MouseEvent.BUTTON3 )
        {
            //if ( scene.getEngine().getItemsInRect(buildCatchArea()).getMassList().isEmpty()  )
            if ( SceneHelper.getItemsInRect(scene, buildCatchArea()).getMassList().isEmpty()  )
            {
                CC.MC.setMouseOTFMode( MouseOTFMode.SCROLL_GRAPHIC_PANEL );
                CC.MC.setMouseOTFSubMode( MouseOTFSubMode.DO_NOTHING );
                CC.MC.mouseLastCursor = owner.getCursor();
                scene.EC.setCursor( new Cursor(Cursor.MOVE_CURSOR) );
            }
            switch( CC.MC.getMouseMode() )
            {
                case ADD_SINGLE_MASS : removeMass2d(evt); break;
                case ADD_SINGLE_WALL : removeWall2d(evt); break;
                case ADD_SINGLE_SPRING : removeSpring2d(evt); break;
                case ADD_SINGLE_RSPRING : removeRSpring2d(evt); break;
            }
        }
    }

    public void mouseReleased(MouseEvent evt) 
    {
        if ( evt.getButton() == MouseEvent.BUTTON1 )
            if ( CC.MC.getMouseOTFMode() != MouseOTFMode.DO_NOTHING )
                switch( CC.MC.getMouseOTFMode() )
                {
                    case SCALE_ACTION_FRAME_NW :
                    case SCALE_ACTION_FRAME_N :
                    case SCALE_ACTION_FRAME_NE :
                    case SCALE_ACTION_FRAME_E :
                    case SCALE_ACTION_FRAME_SE :
                    case SCALE_ACTION_FRAME_S :
                    case SCALE_ACTION_FRAME_SW :
                    case SCALE_ACTION_FRAME_W :
                        scene.EC.setCursor( CC.MC.mouseLastCursor );
                        CC.MC.setMouseOTFMode( MouseOTFMode.DO_NOTHING );
                        CC.MC.setMouseOTFSubMode( MouseOTFSubMode.DO_NOTHING );
                        break;
                }
            else
                switch( CC.MC.getMouseMode() )
                {
                    case ADD_MANY_MASS : stopAddManyMass2d(evt); break;
                    case MOVE_MASSES : stopMoveManyMass2d(evt); break;
                    case CREATE_CIRCLE :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT :
                                stopCreateCircle(evt);
                                CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT );
                                owner.repaint();
                                break;
                        }
                        break;
                    case CREATE_SQUARENET :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT :
                                stopCreateSquareNet(evt);
                                CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT );
                                owner.repaint();
                                break;
                        }
                        break;
                    case SELECT_ALL_ITEMS :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT : stopSelectionAll(evt); break;
                        }
                        break;
                    case SELECT_MASSES :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT : stopSelectionMasses(evt); break;
                        }
                        break;
                    case SELECT_SPRINGS :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT : stopSelectionSprings(evt); break;
                        }
                        break;
                    case SELECT_RSPRINGS :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT : stopSelectionRSprings(evt); break;
                        }
                        break;
                    case SELECT_WALLS :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT : stopSelectionWalls(evt); break;
                        }
                        break;
                    case SELECT_MASSES_IN_ORDER :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT : stopSelectionInOrder(evt); break;
                        }
                        break;
                    case ROTATE :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT : stopRotation(evt); break;
                        }
                        break;
                    case SCALE :
                        switch( CC.MC.getMouseSubMode() )
                        {
                            case FIND_SECOND_OBJECT : stopScaling(evt); break;
                        }
                        break;
                }
        else if ( evt.getButton() == MouseEvent.BUTTON3 )
        {
            if ( CC.MC.getMouseOTFMode() != MouseOTFMode.DO_NOTHING )
                switch( CC.MC.getMouseOTFMode() )
                {
                    case SCROLL_GRAPHIC_PANEL :
                        scene.EC.setCursor( CC.MC.mouseLastCursor );
                        CC.MC.setMouseOTFMode( MouseOTFMode.DO_NOTHING );
                        CC.MC.setMouseOTFSubMode( MouseOTFSubMode.DO_NOTHING );
                        break;
                }
            else
                switch( CC.MC.getMouseMode() )
                {
                }
        }
    }

    public void mouseEntered(MouseEvent arg0) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public void mouseExited(MouseEvent arg0) {
        //throw new UnsupportedOperationException("Not supported yet.");
    }

    private Rect2d buildCatchArea()
    {
        GraphicPanel graphicPanel = (GraphicPanel) owner;
        double x1 = scene.EC.engCursor.getX() - MOVE_MANY_MASS2D_RECT2D_SIZE/graphicPanel.getViewScale();
        double y1 = scene.EC.engCursor.getY() - MOVE_MANY_MASS2D_RECT2D_SIZE/graphicPanel.getViewScale();
        double x2 = scene.EC.engCursor.getX() + MOVE_MANY_MASS2D_RECT2D_SIZE/graphicPanel.getViewScale();
        double y2 = scene.EC.engCursor.getY() + MOVE_MANY_MASS2D_RECT2D_SIZE/graphicPanel.getViewScale();
        return new Rect2d( x1, y1, x2, y2 );
    }
    
    public void addMass2d(MouseEvent evt)
    {
        double x = scene.EC.engCursor.getX();
        double y = scene.EC.engCursor.getY();

        if (scene.EC.currentBody instanceof SpringBody)
        {
            Mass mass;
            SpringBody sb = (SpringBody) scene.EC.currentBody;
            switch( CC.MC.getMouseModeAlt(CC.MC.getMouseMode()) )
            {
                case NORMAL :
                    mass = new Mass( x, y, 1.);//, START_MASS_BOUNCE_FACTOR, START_MASS_FRICTION_FACTOR);
                    SA_Mass.addMassToSpringBody(mass, sb, true);
                    break;
                case INSERT :
                    mass = new Mass( x, y, 1.);//, START_MASS_BOUNCE_FACTOR, START_MASS_FRICTION_FACTOR);
                    //ArrayList<Mass> list = scene.getEngine().getSpringBodyMassesClosestToVec2d(scene.EC.engCursor, 3);
                    ArrayList<Mass> list = SceneHelper.getSpringBodyMassesClosestToVec2d(scene, scene.EC.engCursor, 3);
                    SA_Mass.addMassToSpringBody(mass, sb, false);
                    if (!list.isEmpty())
                        for(Mass m : list) {
                            Spring s = new Spring(mass, m, Spring.Type.SpringBody);
                            SA_Spring.addSpringToSpringBody(s, sb, false);
                        }
                    DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged(sb);
                    break;
            }
            owner.repaint();
        }
    }
    public void startAddManyMass2d(MouseEvent evt)
    {
        if (scene.EC.currentBody instanceof SpringBody)
        {
            // flaga oznaczajaca aktywnosc "sypania" masami
            CC.continous_ADD_MANY_MASS2D = true;

            // wektor wskazujacy aktualna pozycję sypania
            CC.addManyMass2dVec2d = new Vec2d(scene.EC.engCursor.getX(), scene.EC.engCursor.getY());

            final JETContext tmpEngine = scene.getJETContext();
            final SpringBody tmpSpringBody = (SpringBody) scene.EC.currentBody;

            // watek obslugujacy "sypanie"
            (CC.addManyMass2dThread = new Thread( new Runnable()
            {
                public void run()
                {
                    try
                    {
                        while( !Thread.interrupted() )
                        {
                            if ( scene.EC.currentBody != null )
                                SA_Mass.addMassToSpringBody(new Mass( CC.addManyMass2dVec2d.getX(),CC.addManyMass2dVec2d.getY(), 1),
                                                                  (SpringBody)scene.EC.currentBody, true);
                            owner.repaint();
                            Thread.sleep(10);
                        }
                    }catch(InterruptedException ie){ System.out.println("Wystapil wyjatek przerwania watku sypania masami. \nie="+ie); }
                }
            })).start();
        }
    }
    public void stopAddManyMass2d(MouseEvent evt)
    {
        CC.continous_ADD_MANY_MASS2D = true;
        CC.MC.mouseEvent = evt;
        CC.addManyMass2dThread.interrupt();
    }

    public void startMoveItems(MouseEvent evt)
    {
        switch( CC.MC.getMouseModeAlt(CC.MC.getMouseMode()) ) {
            case CLOSEST :
                startMoveMassClosest(evt);
                break;
            case SPECYFIC :
                startMoveItemsSpecyfic(evt);
                break;
        }
    }
    private void startMoveMassClosest(MouseEvent evt) {
        if (CC.isSceneAnimated(scene.getName()))
        {
            Object closest = SceneHelper.getItemClosestToVec2d(scene, gp.scrToEngineVec(MouseHelper.getVec2d(evt)));
            if (closest instanceof Mass)
            {
                Mass draggedMass = (Mass) closest;
                SpringBody draggedSB = SceneHelper.getSpringBodyThatOwnMass(scene, draggedMass);

                Mass tmpMass = new Mass(gp.scrToEngineX(evt.getX()), gp.scrToEngineY(evt.getY()), 1.);
                tmpMass.setMoveable(false);
                Spring tmpSpring = new Spring(tmpMass, draggedMass, Spring.Type.Engine, 0.);
                // Calculate spring stiffness according to dragged body mass
                double ks = draggedSB.getMass()*0.2;
                tmpSpring.setKs(ks);

                SpringBody tmpSb = new SpringBody();
                tmpSb.addMass(tmpMass);

                // Mouse Object1 contains temporary mass, which position refers to actual mouse engine position
                CC.MC.mouseObject1 = tmpMass;

                // Mouse Object2 contains temporary spring used for force calculations
                CC.MC.mouseObject2 = tmpSpring;
                Animator anim = CC.getSceneAnimator(scene.getName());
                anim.context.addSpring(tmpSpring);

                // Mouse Object3 contains temporary spring body inserted temporary into engine springbody list
                CC.MC.mouseObject3 = tmpSb;
                anim.context.addSpringBody(tmpSb);
            }
            else if (closest instanceof RigidBody)
            {
                double engX = gp.scrToEngineX(evt.getX());
                double engY = gp.scrToEngineY(evt.getY());
                RigidBody rb = (RigidBody) closest;
                int closestIndex = RigidBodyHelper.getRigidBodyVertexIndexClosestToVec(rb, new Vec2d(engX, engY));

                Mass tmpMass = new Mass(engX, engY, 1.);
                tmpMass.setMoveable(false);

                Spring tmpSpring = new Spring(Spring.Type.Engine);

                Vec2d v = new Vec2d(rb.dynVecList.get(closestIndex).getPosition());
                rb.sceneToBase(v);
                Mass rbMass = rb.createExtraMass(v.x, v.y);

                tmpSpring.setM1(tmpMass);
                tmpSpring.setM2(rbMass);
                
                // Calculate spring stiffness according to dragged body mass
                double ks = rb.mass *0.1;
                tmpSpring.setKs(ks);
                tmpSpring.setKd(1);

                SpringBody tmpSb = new SpringBody();
                tmpSb.addMass(tmpMass);

                // Mouse Object1 contains temporary mass, which position refers to actual mouse engine position
                CC.MC.mouseObject1 = tmpMass;

                // Mouse Object2 contains temporary spring used for force calculations
                CC.MC.mouseObject2 = tmpSpring;
                Animator anim = CC.getSceneAnimator(scene.getName());
                anim.context.addSpring(tmpSpring);

                // Mouse Object3 contains temporary spring body inserted temporary into engine springbody list
                CC.MC.mouseObject3 = tmpSb;
                anim.context.addSpringBody(tmpSb);
            }

            CC.continous_MOVE_MANY_MASS2D = true;
            CC.MC.setMouseSubMode(MouseSubMode.FIND_SECOND_OBJECT);
            CC.MC.mouseEvent = evt;
            owner.repaint();
        }
    }
    private void startMoveItemsSpecyfic(MouseEvent evt) {
        CC.moveManyMass2dCatchArea = buildCatchArea();

        CC.ctrlMass2dList = SceneHelper.getSpringBodyMassInRect2dList(scene, CC.moveManyMass2dCatchArea);

        if ( !CC.ctrlMass2dList.isEmpty() )
            for ( Mass mass : CC.ctrlMass2dList ) {
                mass.setWasMoveable( mass.isMoveable() );
                mass.setMoveable( false );
            }
        else if ( !scene.EC.selectionGroup.getMassList().isEmpty() ) {
            Collection<Mass> massCol = scene.EC.selectionGroup.getMassListSync();
                synchronized(massCol) {
                    for ( Mass mass : massCol ) {
                        mass.setWasMoveable( mass.isMoveable() );
                        mass.setMoveable( false );
                    }
                }
        }
        else
        {
            findActualBody(evt);
            if (scene.EC.currentBody instanceof SpringBody) {
                Collection<Mass> massCol = ((SpringBody)scene.EC.currentBody).getMassListSync();
                synchronized(massCol) {
                    for ( Mass mass : massCol ) {
                        mass.setWasMoveable( mass.isMoveable() );
                        mass.setMoveable( false );
                    }
                }
            }
            else if (scene.EC.currentBody instanceof RigidBody) {
                
            }
        }

        CC.continous_MOVE_MANY_MASS2D = true;
        CC.MC.setMouseSubMode(MouseSubMode.FIND_SECOND_OBJECT);
        CC.MC.mouseEvent = evt;
        owner.repaint();
    }
    public void stopMoveManyMass2d(MouseEvent evt) {
        switch( CC.MC.getMouseModeAlt(CC.MC.getMouseMode())) {
            case CLOSEST :
                stopMoveManyMass2dClosest(evt);
                break;
            case SPECYFIC :
                stopMoveManyMass2dSpecyfic(evt);
                break;
        }
    }
    synchronized public void stopMoveManyMass2dClosest(MouseEvent evt) {
        if (CC.isSceneAnimated(scene.getName()))
        {
            Animator anim = CC.getSceneAnimator(scene.getName());
            anim.context.getSpringList().remove((Spring)CC.MC.mouseObject2);
            anim.context.removeSpringBody((SpringBody)CC.MC.mouseObject3);

            CC.continous_MOVE_MANY_MASS2D = false;
            CC.MC.setMouseSubMode(MouseSubMode.FIND_FIRST_OBJECT);
            CC.MC.mouseEvent = evt;
            owner.repaint();
        }
    }
    
    public void stopMoveManyMass2dSpecyfic(MouseEvent evt) {
        if ( CC.ctrlMass2dList.size()>0 )
            for ( Mass mass : CC.ctrlMass2dList )
                mass.setMoveable( mass.wasMoveable() );
        else if ( !scene.EC.selectionGroup.getMassList().isEmpty() )
            for ( Mass mass : scene.EC.selectionGroup.getMassList() )
                mass.setMoveable( mass.wasMoveable() );
        else if (scene.EC.currentBody instanceof SpringBody) {
            SpringBody sb = (SpringBody) scene.EC.currentBody;
            Collection<Mass> massCol = sb.getMassListSync();
            synchronized(massCol) {
                for (Mass mass : massCol)
                    mass.setMoveable( mass.wasMoveable() );
            }
        }

        CC.continous_MOVE_MANY_MASS2D = false;
        CC.MC.setMouseSubMode(MouseSubMode.FIND_FIRST_OBJECT);
        CC.MC.mouseEvent = evt;
        owner.repaint();
    }
    public void startAddWall2d(MouseEvent evt)
    {
        Rect2d rect2d = buildCatchArea();
        
//        Mass mass = scene.getEngine().getSpringBodyMassInRect2d(rect2d);
        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, rect2d);
        if ( mass != null )
        {
            CC.MC.mouseObject1 = mass;
            CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
            CC.MC.mouseEvent = evt;
            return;
        }
    }
    public void stopAddWall2d(MouseEvent evt)
    {
        Rect2d rect2d = buildCatchArea();
        
//        Mass mass = scene.getEngine().getSpringBodyMassInRect2d(rect2d);
        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, rect2d);
        if ( mass != null && !CC.MC.mouseObject1.equals(mass) )
        {
//            SpringBody springBody = scene.getEngine().getSpringBodyThatOwnMass(mass);
            SpringBody springBody = SceneHelper.getSpringBodyThatOwnMass(scene, mass);
            Wall wall = new Wall((Mass)CC.MC.mouseObject1, mass);
            SA_Wall.addWallToSpringlBody(wall, springBody, true);
            CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
            CC.MC.mouseObject1 = mass;
            CC.MC.mouseEvent = evt;
            owner.repaint();
            DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged(springBody);
            return;
        }
    }
    public void removeMass2d(MouseEvent evt)
    {
        CC.moveManyMass2dCatchArea = buildCatchArea();

//        Mass mass = scene.getEngine().getSpringBodyMassInRect2d( CC.moveManyMass2dCatchArea );
        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, CC.moveManyMass2dCatchArea);
        if ( mass != null )
        {
//            SpringBody sb = scene.getEngine().getSpringBodyThatOwnMass(mass);
            SpringBody sb = SceneHelper.getSpringBodyThatOwnMass(scene, mass);
            SA_Mass.removeMassFromSpringBody(mass, scene, true);
            owner.repaint();
            return;
        }
    }
    public void removeWall2d(MouseEvent evt)
    {
        GraphicPanel gp = (GraphicPanel) owner;
//        Wall wall = scene.getEngine().getSpringBodyWallAtPos( new Vec2d( gp.scrToEngineX(evt.getX()),
//                                                              gp.scrToEngineY(evt.getY())),
//                                                              gp.getViewScale() );
        Wall wall = SceneHelper.getSpringBodyWallAtPos(scene,  new Vec2d( gp.scrToEngineX(evt.getX()),
                                                              gp.scrToEngineY(evt.getY())),
                                                              gp.getViewScale() );
        if ( wall != null )
        {
//            SpringBody sb = scene.getEngine().getSpringBodyThatOwnWall(wall);
            SpringBody sb = SceneHelper.getSpringBodyThatOwnWall(scene, wall);
            SA_Wall.removeWallFromSpringBody(wall, scene, true);
            owner.repaint();
            return;
        }
    }
    public void removeSpring2d(MouseEvent evt)
    {
        GraphicPanel gp = (GraphicPanel) owner;
        Vec2d wherePos = new Vec2d( gp.scrToEngineX(evt.getX()), gp.scrToEngineY(evt.getY()));

        Spring  spring = SceneHelper.getSpringBodySpringAtPos(scene, wherePos, gp.getViewScale());
        if ( spring != null )
        {
            SA_Spring.removeSpringFromSpringBody(spring, scene, true);
            return;
        }

        spring = scene.getJETContext().getSpringAtPos( wherePos, gp.getViewScale() );
        if ( spring != null)
        {
            SA_Spring.removeSpringFromEngine(spring, scene);
            return;
        }
    }
    public void removeRSpring2d(MouseEvent evt)
    {
        GraphicPanel gp = (GraphicPanel) owner;
        Vec2d wherePos = new Vec2d( gp.scrToEngineX(evt.getX()), gp.scrToEngineY(evt.getY()));

        RSpring  rs = SceneHelper.getSpringBodyRSpringAtPos(scene, wherePos, gp.getViewScale());
        if ( rs != null )
        {
            SpringBody sb = SceneHelper.getSpringBodyThatOwnRSpring(scene, rs);
            SA_RSpring.removeRSpringFromSpringBody(rs, scene, true);
            return;
        }

        rs = scene.getJETContext().getRSpringAtPos( wherePos, gp.getViewScale() );
        if ( rs != null)
        {
            SA_RSpring.removeRSpringFromEngine(rs, scene);
            return;
        }
    }
    public void startAddSpring(MouseEvent evt)
    {
        Rect2d rect2d = buildCatchArea();
        
        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, rect2d);
        if ( mass != null )
        {
            CC.MC.mouseObject1 = mass;
            CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
            CC.MC.mouseEvent = evt;
            return;
        }

        RigidBody rb = SceneHelper.getRigidBodyAt(scene, scene.EC.engCursor);
        if ( rb != null )
        {
            CC.MC.mouseObject1 = rb;
            CC.MC.mouseVec = new Vec2d(scene.EC.engCursor);
            CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
            CC.MC.mouseEvent = evt;
            return;
        }
    }
    public void stopAddSpring(MouseEvent evt)
    {
        Rect2d      rect2d = buildCatchArea();
        Spring      s = null;
        SceneItem   si1 = null,
                    si2 = null;

        boolean gotoFinish = false; // if found someitem (ex. mass) do not look for other possible items
       
        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, rect2d);
        if ( mass != null && (CC.MC.mouseObject1==null || !CC.MC.mouseObject1.equals(mass)) )
        {
            if (CC.MC.mouseObject1 instanceof Mass)
            {
                Mass mass1 = (Mass)CC.MC.mouseObject1;
                Mass mass2 = mass;

                SpringBody sb1 = SceneHelper.getSpringBodyThatOwnMass(scene, mass1);
                SpringBody sb2 = SceneHelper.getSpringBodyThatOwnMass(scene, mass2);

                si1 = SceneHelper.getSceneItemThatOwnSpringBody(scene, sb1);
                si2 = SceneHelper.getSceneItemThatOwnSpringBody(scene, sb2);


                if (sb1.equals(sb2))
                {
                    s = new Spring(mass1, mass2, Spring.Type.SpringBody);
                    SA_Spring.addSpringToSpringBody(s, sb1, true);
                    //DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged(sb1);
                }
                else if (si1!=null && si2!=null && si1.equals(si2))
                {
                    s = new Spring(mass1, mass2, Spring.Type.SceneItem);
                    //SA_Spring.addSpringToSceneItem(s, si1, true);
                }
                else
                {
                    s = new Spring(mass1, mass2, Spring.Type.Engine);
                    SA_Spring.addSpringToEngineList(s, scene);
                    DataModelsFactory.getSceneTreeModel().fireSceneSpringsChanged();
                }
            }
            else if (CC.MC.mouseObject1 instanceof RigidBody)
            {
                RigidBody rb = (RigidBody) CC.MC.mouseObject1;
                s = new Spring(Spring.Type.Engine);

                Vec2d baseVec = new Vec2d(CC.MC.mouseVec.x, CC.MC.mouseVec.y);
                rb.sceneToBase(baseVec);
                Mass mass1 = rb.createExtraMass(baseVec.x, baseVec.y);
                Mass mass2 = mass;

                s.setM1(mass1);
                s.setM2(mass2);
                s.setStartLength(s.getVector().getMagnitude());
                
                SA_Spring.addSpringToEngineList(s, scene);
                DataModelsFactory.getSceneTreeModel().fireSceneSpringsChanged();
            }

            gotoFinish = true;
        }

        RigidBody rb = SceneHelper.getRigidBodyAt(scene, scene.EC.engCursor);
        if (rb != null && (CC.MC.mouseObject1==null || !CC.MC.mouseObject1.equals(rb))
            && !gotoFinish)
        {
            if (CC.MC.mouseObject1 instanceof Mass)
            {
                s = new Spring(Spring.Type.Engine);

                Vec2d baseVec = new Vec2d(scene.EC.engCursor.x, scene.EC.engCursor.y);
                rb.sceneToBase(baseVec);
                Mass mass1 = (Mass) CC.MC.mouseObject1;
                Mass mass2 = rb.createExtraMass(baseVec.x, baseVec.y);

                s.setM1(mass1);
                s.setM2(mass2);
                s.setStartLength(s.getVector().getMagnitude());

                SA_Spring.addSpringToEngineList(s, scene);
                DataModelsFactory.getSceneTreeModel().fireSceneSpringsChanged();
            }
            else if (CC.MC.mouseObject1 instanceof RigidBody)
            {
                RigidBody rb1 = (RigidBody) CC.MC.mouseObject1;
                s = new Spring(Spring.Type.Engine);

                Vec2d baseVec = new Vec2d(CC.MC.mouseVec.x, CC.MC.mouseVec.y);
                rb1.sceneToBase(baseVec);
                Mass mass1 = rb1.createExtraMass(baseVec.x, baseVec.y);

                baseVec.setXY(scene.EC.engCursor.x, scene.EC.engCursor.y);
                rb.sceneToBase(baseVec);
                Mass mass2 = rb.createExtraMass(baseVec.x, baseVec.y);

                s.setM1(mass1);
                s.setM2(mass2);
                s.setStartLength(s.getVector().getMagnitude());

                SA_Spring.addSpringToEngineList(s, scene);
                DataModelsFactory.getSceneTreeModel().fireSceneSpringsChanged();
            }
        }

        if (s!=null) {
            switch(s.getType()) {
                case Engine: DataModelsFactory.getSceneTreeModel().fireSceneRSpringsChanged(); break;
                case SceneItem: DataModelsFactory.getSceneItemsTreeModel().fireSpringItemChanged(si1);  break;
                case SpringBody:
                    SpringBody sb = SceneHelper.getSpringBodyThatOwnSpring(scene, s);
                    switch(sb.getOwnerType()) {
                        case Engine: DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged(sb); break;
                        case SceneItem: DataModelsFactory.getSceneItemsTreeModel().fireSpringBodyChanged(sb); break;
                    }
                    break;
            }

            if (mass != null) {
                CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
                CC.MC.mouseObject1 = mass;
                System.out.println("finished at mass...");
            } else if (rb != null) {
                CC.MC.getMouseModeSequence().clear();
                CC.MC.getMouseModeSequence().addTask( new AddSingleSpringTask());
                CC.MC.getMouseModeSequence().begin();
                CC.GUIC.repaintAllSceneTabs();
                System.out.println("finished at rb...");
            }
            CC.MC.mouseEvent = evt;
        }
    }

    public void copySelectedItems(MouseEvent evt)
    {
        if ( !scene.EC.selectionGroup.getMassList().isEmpty() )
        {
            Vec2d offset = new Vec2d(scene.EC.engCursor);
            offset.sub( scene.EC.selectionGroup.getMassCenterVec() );

            SpringBody sb = new SpringBody();
            SA_SpringBody.addSpringBodyToScene(sb, scene, false);
            StaticActions.copySelectedItemsIntoSpringBody(sb, scene);
            sb.moveBy(offset);
//            StaticActions.clearSelection();
//            StaticActions.addSpringBodyToSelection(sb);
        }
    }

    public void setMoveable(MouseEvent evt)
    {
        Rect2d rect2d = buildCatchArea();

        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, rect2d);
        if ( mass != null )
        {
            mass.setMoveable( !mass.isMoveable() );
            owner.repaint();
        }
        else if ( !scene.EC.selectionGroup.getMassList().isEmpty() )
        {
            for(Mass m : scene.EC.selectionGroup.getMassList() )
                m.setMoveable( !m.isMoveable() );
            owner.repaint();
        }
        else if (scene.EC.currentBody instanceof SpringBody) {
            SpringBody sb = (SpringBody) scene.EC.currentBody;
            Collection<Mass> massCol = sb.getMassListSync();
            synchronized(massCol) {
                for(Mass m : massCol)
                    m.setMoveable( !m.isMoveable() );
            }
            owner.repaint();
        }
    }
    

    public void startRotation(MouseEvent evt)
    {
        CC.MC.mouseVec = new Vec2d( scene.EC.engCursor );
        scene.EC.transformMassList.clear();
        for (int i=0; i<scene.EC.selectionGroup.getMassList().size(); i++)
            scene.EC.transformMassList.add( new Mass( scene.EC.selectionGroup.getMassList().get(i)) );

        CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
    }

    public void stopRotation(MouseEvent evt)
    {
        for (int i=0; i<scene.EC.selectionGroup.getMassList().size(); i++)
        {
            Mass mass = scene.EC.selectionGroup.getMassList().get(i);
            mass.getPosition().become( scene.EC.transformMassList.get(i).getPosition() );
        }
        
        CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT );
    }

    public void startScaling(MouseEvent evt)
    {
        CC.MC.mouseVec = new Vec2d( scene.EC.engCursor );
        scene.EC.transformMassList.clear();
        for (int i=0; i<scene.EC.selectionGroup.getMassList().size(); i++)
            scene.EC.transformMassList.add( new Mass( scene.EC.selectionGroup.getMassList().get(i)) );

        CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
    }

    public void stopScaling(MouseEvent evt)
    {
        for (int i=0; i<scene.EC.selectionGroup.getMassList().size(); i++)
        {
            Mass mass = scene.EC.selectionGroup.getMassList().get(i);
            mass.getPosition().become( scene.EC.transformMassList.get(i).getPosition() );
        }

        CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT );
    }
    
    public void breakRotation(MouseEvent evt)
    {
        CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT );
        owner.repaint();
    }

    public void startCreateCircle(MouseEvent evt)
    {
        CC.MC.mouseVec = new Vec2d(scene.EC.engCursor);
        CC.MC.mouseVec2 = new Vec2d(scene.EC.engCursor);

        if (CC.MC.mouseInteger<3) CC.MC.mouseInteger = 3;
        if ( CC.MC.createCircleCenterPoint && CC.MC.createCircleDoubleSprings &&
             CC.MC.mouseInteger%2!=0 ) CC.MC.mouseInteger++;
            
        CC.MC.mouseEvent = evt;
        CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
    }
    public void stopCreateCircle(MouseEvent evt)
    {
        ArrayList<Object> list = null;
        
        if ( CC.MC.createCircleCenterPoint && CC.MC.createCircleDoubleSprings )
        {
            list = BodyFactory.bulidCenterPointCircleWithDoubleSprings(
                                CC,
                                CC.MC.mouseVec,
                                CC.MC.mouseVec2, //new Vec2d(evt.getX(), evt.getY()),
                                CC.MC.mouseInteger,
                                1, 
                                START_MASS_BOUNCE_FACTOR,
                                START_MASS_FRICTION_FACTOR);
        }
        else if ( CC.MC.createCircleCenterPoint )
        {
            list = BodyFactory.bulidCenterPointCircle(
                                CC,
                                CC.MC.mouseVec,
                                CC.MC.mouseVec2, //new Vec2d(evt.getX(), evt.getY()),
                                CC.MC.mouseInteger,
                                1, 
                                START_MASS_BOUNCE_FACTOR,
                                START_MASS_FRICTION_FACTOR);
        }
        else
        {
            list = BodyFactory.bulidCircle(
                                CC,
                                CC.MC.mouseVec,
                                CC.MC.mouseVec2, //new Vec2d(evt.getX(), evt.getY()),
                                CC.MC.mouseInteger,
                                1,
                                START_MASS_BOUNCE_FACTOR,
                                START_MASS_FRICTION_FACTOR);
        }

        if (list != null)
        {
                if ( CC.createNewSpringBody ) SA_SpringBody.addSpringBodyToScene(scene, true);
                if ( scene.EC.currentBody != null)
                {
                    Collection<Mass> massCol = Collections.synchronizedList((ArrayList<Mass>)list.get(0));
                    synchronized(massCol) {
                        SA_Mass.addMassListToSpringBody(massCol, (SpringBody) scene.EC.currentBody, false);
                    }
                    if (CC.MC.createCircleWalls ) {
                        Collection<Wall> wallCol = Collections.synchronizedList((ArrayList<Wall>) list.get(1));
                        synchronized(wallCol) {
                            SA_Wall.addWallListToSpringBody(wallCol, (SpringBody) scene.EC.currentBody, false);
                        }
                    }

                    Collection<Spring> springCol = Collections.synchronizedList((ArrayList<Spring>) list.get(2));
                    synchronized(springCol) {
                        SA_Spring.addSpringListToSpringBody(springCol, (SpringBody) scene.EC.currentBody, false);
                    }
                    scene.EC.currentBody.getBorder().checkIfBorderIsProper();

                    DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged((SpringBody) scene.EC.currentBody);
                }
        }
    }
    public void startCreateSquareNet(MouseEvent evt)
    {
        CC.MC.mouseVec = new Vec2d(scene.EC.engCursor);
        CC.MC.mouseVec2 = new Vec2d(scene.EC.engCursor);


        if (CC.MC.mouseInteger<1) CC.MC.mouseInteger = 1;
        CC.MC.mouseEvent = evt;
        CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
    }
    public void stopCreateSquareNet(MouseEvent evt)
    {
        ArrayList<Object> list = null;
        switch(CC.MC.bodyType) {
            case Spring:
                list = BodyFactory.buildSquareNet(
                            CC, CC.MC.createSquareNetDoubleSprings, CC.MC.mouseInteger,
                            CC.MC.mouseVec,
                            CC.MC.mouseVec2, //new Vec2d(evt.getX(), evt.getY()),
                            1.0,
                            START_MASS_BOUNCE_FACTOR,
                            START_MASS_FRICTION_FACTOR);

                if (list != null) {
                    if ( CC.createNewSpringBody ) SA_SpringBody.addSpringBodyToScene(scene, true);
                    if ( scene.EC.currentBody != null) {
                        SA_Mass.addMassListToSpringBody((ArrayList<Mass>) list.get(0), (SpringBody) scene.EC.currentBody, false);
                        SA_Wall.addWallListToSpringBody((ArrayList<Wall>) list.get(1), (SpringBody) scene.EC.currentBody, false);
                        SA_Spring.addSpringListToSpringBody((ArrayList<Spring>) list.get(2), (SpringBody) scene.EC.currentBody, false);
                        scene.EC.currentBody.getBorder().checkIfBorderIsProper();

                        DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged((SpringBody) scene.EC.currentBody);
                    }
                }
                break;
            case Rigid:
                RigidBody rb = RigidBodyFactory.buildRect(CC.MC.mouseVec.x, CC.MC.mouseVec.y,
                                                          CC.MC.mouseVec2.x, CC.MC.mouseVec2.y,
                                                          10);
                scene.EC.currentBody = rb;
                SA_RigidBody.addRigidBodyToScene(scene, rb);
                break;
        }
        
    }

    public synchronized void startSelection(MouseEvent evt)
    {
        CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
        CC.MC.mouseVec = new Vec2d( gp.scrToEngineX(evt.getX()), gp.scrToEngineY(evt.getY()) );
        
        if ( !evt.isControlDown() ) {
            SA_Selection.clearSelection(scene);
        }
        
        scene.EC.selectionRect = null;
    }

    public synchronized void stopSelectionAll(MouseEvent evt)
    {
        final SelectionGroup selection = (SelectionGroup) scene.EC.tempSelectGroup.Clone();
        CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT);
        CC.MC.mouseVec = null;

        /*CC.cachedThreadPoll.execute( new Runnable() {
            public void run(){ */
                for(Mass mass : selection.getMassList())
                    SA_Selection.addMassToSelection(mass, scene, true);
            /*}
        });*/

        /*CC.cachedThreadPoll.execute( new Runnable() {
            public void run(){*/
                for(Spring spring : selection.getSpringList())
                    SA_Selection.addSpringToSelection(spring, scene, true);
            /*}
        });*/

        /*CC.cachedThreadPoll.execute( new Runnable() {
            public void run(){*/
                for(RSpring rs : selection.getRSpringList())
                    SA_Selection.addRSpringToSelection(rs, scene, true);
            /*}
        });*/

        /*CC.cachedThreadPoll.execute( new Runnable() {
            public void run(){*/
                for(Wall wall : selection.getWallList())
                    SA_Selection.addWallToSelection(wall, scene, true);
            /*}
        });*/

        SA_Dialogs.fillPropertiesDialogWithMassData(scene);
        SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
        SA_Dialogs.fillPropertiesDialogWithRSpringData(scene);

        scene.EC.selectionGroup.setMassesInOrder(false);
        scene.EC.tempSelectGroup.clear();
        owner.repaint();
    }
    
    public synchronized void stopSelectionMasses(MouseEvent evt)
    {
        CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT);
        CC.MC.mouseVec = null;

        for(Mass mass : scene.EC.tempSelectGroup.getMassList())
            if ( !scene.EC.selectionGroup.getMassList().contains(mass) )
                SA_Selection.addMassToSelection(mass, scene, true);

        SA_Dialogs.fillPropertiesDialogWithMassData(scene);

        scene.EC.selectionGroup.setMassesInOrder(false);
        scene.EC.tempSelectGroup.clear();
        owner.repaint();
    }
    
    public synchronized void stopSelectionSprings(MouseEvent evt)
    {
        final SelectionGroup selection = (SelectionGroup) scene.EC.tempSelectGroup.Clone();

        CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT);
        CC.MC.mouseVec = null;

        /*CC.cachedThreadPoll.execute(new Runnable() {
            public void run() {*/
                Collection<Spring> springCol = selection.getSpringListSync();
                synchronized(springCol) {
                    for(Spring spring : springCol) {
                        SA_Selection.addSpringToSelection(spring, scene, false);
                    }
                }
            /*}
        });*/

       SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
        
        scene.EC.tempSelectGroup.clear();
        owner.repaint();
    }

    public synchronized void stopSelectionRSprings(MouseEvent evt)
    {
        CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT);
        CC.MC.mouseVec = null;

        for(RSpring rs : scene.EC.tempSelectGroup.getRSpringList())
            if ( !scene.EC.selectionGroup.getRSpringList().contains(rs) )
                SA_Selection.addRSpringToSelection(rs, scene, true);

        SA_Dialogs.fillPropertiesDialogWithRSpringData(scene);

        scene.EC.tempSelectGroup.clear();
        owner.repaint();
    }

    public synchronized void stopSelectionWalls(MouseEvent evt)
    {
        CC.MC.setMouseSubMode( MouseSubMode.FIND_FIRST_OBJECT);
        CC.MC.mouseVec = null;

        for(Wall wall : scene.EC.tempSelectGroup.getWallList())
            if ( !scene.EC.selectionGroup.getWallList().contains(wall) )
                SA_Selection.addWallToSelection(wall, scene, true);

        scene.EC.tempSelectGroup.clear();
        owner.repaint();
    }

    public SpringBody selectSpringBody(MouseEvent evt)
    {
        Vec2d engineMousePosition = new Vec2d( gp.scrToEngineX(evt.getX()), gp.scrToEngineY(evt.getY()) );

        SpringBody sb = null;
        if ((sb = SceneHelper.getSpringBodyAt(scene, engineMousePosition)) != null)
        {
            if (!evt.isControlDown())
                SA_Selection.clearSelection(scene);
            
            SA_SpringBody.setCurrentSpringBody(sb, scene, true);
            SA_Selection.addSpringBodyToSelection(sb, scene, false);

            SA_Dialogs.fillPropertiesDialogWithMassData(scene);
            SA_Dialogs.fillPropertiesDialogWithSpringData(scene);

            owner.repaint();
            return (SpringBody) scene.EC.currentBody;
        }

        return null;
    }

    /**
     * Looks for spring body under mouse pointer and if one is found it becomes 
     * current body.
     * 
     * @param evt
     * @return SpringBody under mouse pointer position from event.
     */
    public Body findActualBody(MouseEvent evt)
    {
        Vec2d engineMousePosition = new Vec2d( gp.scrToEngineX(evt.getX()), gp.scrToEngineY(evt.getY()) );

        SpringBody sb = null;
        if ((sb = SceneHelper.getSpringBodyAt(scene, engineMousePosition)) != null)
        {
            SA_SpringBody.setCurrentSpringBody(sb, scene, true);
            owner.repaint();
            return sb;
        }
        
        RigidBody rb = null;
        if ((rb = SceneHelper.getRigidBodyAt(scene, engineMousePosition)) != null)
        {
            SA_RigidBody.setCurrentRigidBody(rb, scene, true);
            owner.repaint();
            return rb;
        }

        return null;
    }

    public void startSelectionInOrder(MouseEvent evt)
    {
        if ( !evt.isControlDown() )
            scene.EC.selectionGroup.clear();

        scene.EC.vecList.clear();
        scene.EC.vecList.add( new Vec2d(scene.EC.engCursor) );

        CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
    }

    private void stopSelectionInOrder(MouseEvent evt)
    {
        stopSelectionMasses(evt);
    }

    private void startAddRSpring1(MouseEvent evt) {
        Rect2d rect2d = buildCatchArea();

        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, rect2d);
        if ( mass != null )
        {
            CC.MC.mouseObject1 = mass;
            CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
            CC.MC.mouseEvent = evt;
            return;
        }
    }

    private void startAddRSpring2(MouseEvent evt) {
        Rect2d rect2d = buildCatchArea();

        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, rect2d);
        if ( mass != null )
        {
            CC.MC.mouseObject2 = mass;
            CC.MC.setMouseSubMode( MouseSubMode.FIND_THIRD_OBJECT );
            CC.MC.mouseEvent = evt;
            return;
        }
    }

    private void stopAddRSpring(MouseEvent evt) {
        Rect2d rect2d = buildCatchArea();

        Mass mass = SceneHelper.getSpringBodyMassInRect2d(scene, rect2d);
        if ( mass != null )
        {
            SpringBody sb1 = SceneHelper.getSpringBodyThatOwnMass(scene, (Mass)CC.MC.mouseObject1);
            SpringBody sb2 = SceneHelper.getSpringBodyThatOwnMass(scene, (Mass)CC.MC.mouseObject2);
            SpringBody sb3 = SceneHelper.getSpringBodyThatOwnMass(scene, mass);

            SceneItem si1 = SceneHelper.getSceneItemThatOwnSpringBody(scene, sb1);
            SceneItem si2 = SceneHelper.getSceneItemThatOwnSpringBody(scene, sb2);
            SceneItem si3 = SceneHelper.getSceneItemThatOwnSpringBody(scene, sb3);

            RSpring rs = null;
            if (sb1.equals(sb2) && sb2.equals(sb3)) // add rspring to spring body
            {
                rs = new RSpring((Mass)CC.MC.mouseObject1,(Mass)CC.MC.mouseObject2,mass, RSpring.Type.SpringBody);
                SA_RSpring.addRSpringToSpringBody(rs, sb1, true);

                DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged(sb1);
            }
            else if(si1 != null && si2 != null && si3 != null && si1.equals(si2) && si1.equals(si3)) // add rspring to scene item
            {
                rs = new RSpring((Mass)CC.MC.mouseObject1,(Mass)CC.MC.mouseObject2,mass, RSpring.Type.SceneItem);
                SA_RSpring.addRSpringToSceneItem(rs, si1, true);
                //DataModelsFactory.getSceneItemsTreeModel().
            }
            else    // add rspring to engine
            {
                rs = new RSpring((Mass)CC.MC.mouseObject1,(Mass)CC.MC.mouseObject2,mass, RSpring.Type.Engine);
                SA_RSpring.addRSpringToEngineList(rs, scene);
                
            }

            if (rs!=null)
                switch(rs.getType()) {
                    case Engine: DataModelsFactory.getSceneTreeModel().fireSceneRSpringsChanged(); break;
                    case SceneItem: DataModelsFactory.getSceneItemsTreeModel().fireSpringItemChanged(si1); break;
                    case SpringBody:
                        SpringBody sb = SceneHelper.getSpringBodyThatOwnRSpring(scene, rs);
                        switch(sb.getOwnerType()) {
                            case Engine: DataModelsFactory.getSceneTreeModel().fireSpringBodyChanged(sb); break;
                            case SceneItem: DataModelsFactory.getSceneItemsTreeModel().fireSpringBodyChanged(sb); break;
                        }
                        break;
                }

            // continue adding rotary springs from last secelted mass
            CC.MC.mouseObject1 = mass;
            CC.MC.setMouseSubMode( MouseSubMode.FIND_SECOND_OBJECT );
            CC.MC.mouseEvent = evt;
            return;
        }
    }
}